package com.xbongbong.paas.controller.alipay;

import com.xbongbong.alipay.util.AlipayNotify;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.help.EsignHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.esign.pojo.dto.EsignOrderResaleDTO;
import com.xbongbong.pro.esign.pojo.vo.EsignOrderResaleVO;
import com.xbongbong.pro.sms.model.SmsConfigModel;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SmsConfigEntity;
import com.xbongbong.sys.domain.entity.AlipayNotifyEntity;
import com.xbongbong.sys.domain.entity.FeeEntity;
import com.xbongbong.sys.domain.entity.FeeLogEntity;
import com.xbongbong.sys.model.AlipayNotifyModel;
import com.xbongbong.sys.model.FeeLogModel;
import com.xbongbong.sys.model.FeeModel;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static com.xbongbong.saas.help.ProDetailHandlerHelp.LOG;

/**
 * @description: 短信套餐支付宝支付
 * @Author: hongxiao
 * @date: 2019-09-12 15:24
 * @since v1.0
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/mobile/alipay")
public class SmsAlipayController {

    @Resource
    private FeeLogModel feeLogModel;
    @Resource
    private FeeModel feeModel;
    @Resource
    private SmsConfigModel smsConfigModel;
    @Resource
    private AlipayNotifyModel alipayNotifyModel;
    @Resource
    private EsignHelp esignHelp;


    @SuppressWarnings("rawtypes")
    @RequestMapping("/notify/sms")
    public String alipayNotify(HttpServletRequest request,
                               HttpServletResponse response, Map<String, Object> modelMap)
            throws Exception {
        LOG.info("alipayNotify---------" + "intoSms");

        response.setContentType("text/html; charset=UTF-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        // 获取支付宝POST过来反馈信息
        String returnStr = "success";

        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map requestParams = request.getParameterMap();

        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        LOG.info("checkAliPay" + params);
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        //商户订单号

        if (StringUtil.isEmpty(params.get("out_trade_no"))) {

            LOG.error("checkAliPay-failed");
            out.write("fail");
            return null;
        }

        String out_trade_no = params.get("out_trade_no");
        // 支付宝交易号
        String trade_no = params.get("trade_no");
        // 交易状态
        String trade_status = params.get("trade_status");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//

        // 验证成功
        if (AlipayNotify.verify(params)) {

            LOG.info("checkAliPay-verified");

            //请在这里加上商户的业务逻辑程序代码

            //——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

            if (trade_status.equals("TRADE_FINISHED")) {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序
                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序
                //注意：
                //付款完成后，支付宝系统发送该交易状态通知
                saveNotifyEntity(params);

                Map<String, Object> resultMap = feeLogModel.updatePayed(trade_no, out_trade_no);
                String corpid = (String) resultMap.get("corpid");
                Long feeId = (Long) resultMap.get("feeId");
                String corpName = (String) resultMap.get("corpName");
                if (null == feeId) {
                    LOG.error("===========alipay notify error: feeLogModel.updatePayed" + out_trade_no);
                    //TOOD 已付款，但是更新支付状态出错，需要人工干预
                } else {
                    // 充值短信条数
                    FeeEntity feeEntity = feeModel.getByKey(feeId);
                    PackageTypeEnum packageTypeEnum = PackageTypeEnum.getByType(feeEntity.getType());

                    switch (packageTypeEnum) {
                        case SMS:
                            smsRecharge(feeEntity, corpid, corpName);
                            break;
                        case ESIGN:
                            esignRecharge(feeEntity, corpid, out_trade_no);
                            break;
                    }


                    //增加短信条数结束
                }
            }
        } else {
            // 验证失败
            returnStr = "fail";
            LOG.info("checkAliPay-verified-fail");
        }

        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        out.write(returnStr);
        return null;
    }

    /**
     * 短信充值逻辑
     * @param feeEntity
     * @param corpid
     */
    private void smsRecharge(FeeEntity feeEntity, String corpid, String corpName) {
        //user_num作为短信充值数
        Integer smsCount = feeEntity.getPrimaryNum();
        Double realPrice = feeEntity.getRealPrice() == null ? 0.00D : feeEntity.getRealPrice();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.CORPID, corpid);
        List<SmsConfigEntity> lists = smsConfigModel.findEntitys(param);
        if (lists.size() > 0) {
            SmsConfigEntity smsConfigEntity = lists.get(0);
            Integer smsCountBef = smsConfigEntity.getSmsCount();
            String configMemo = smsConfigEntity.getMemo();
            if (null == smsCountBef) {
                smsCountBef = 0;
            }
            // 增加短信剩余发送条数
            smsConfigEntity.setSmsCount(smsCountBef + smsCount);
            if (null == configMemo) {
                configMemo = "";
            }
            configMemo += String.format(I18nMessageUtil.getMessage(I18nStringConstant.SMS_CONFIGMEMO), feeEntity.getRealPrice(), smsCount);
            smsConfigEntity.setMemo(configMemo);

            // 增加短信余额
            Double smsBalance = smsConfigEntity.getSmsBalance() == null ? 0.00D : smsConfigEntity.getSmsBalance();

            Double balanceAmount = Arith.add(smsBalance, realPrice);
            smsConfigEntity.setSmsBalance(balanceAmount);

            smsConfigModel.update(smsConfigEntity);
        } else {
            SmsConfigEntity smsConfigEntity = new SmsConfigEntity();
            smsConfigEntity.setCorpid(corpid);
            smsConfigEntity.setCorpName(corpName);
            smsConfigEntity.setSmsCount(smsCount);
            String configMemo = "充值"+realPrice+"元，增加短信"+smsCount+"条；";
            smsConfigEntity.setMemo(configMemo);

            // 增加短信余额
            smsConfigEntity.setSmsBalance(realPrice);

            smsConfigModel.insert(smsConfigEntity);
        }
    }

    /**
     * e签宝充值逻辑
     * @param feeEntity
     * @param corpid
     */
    private void esignRecharge(FeeEntity feeEntity, String corpid, String orderId) throws XbbException {
        EsignOrderResaleDTO esignOrderResaleDTO = new EsignOrderResaleDTO();
        esignOrderResaleDTO.setCorpId(corpid);
        esignOrderResaleDTO.setOrderId(orderId);
        esignOrderResaleDTO.setItemCode(feeEntity.getId() + "");
        esignOrderResaleDTO.setIteName(feeEntity.getThirdPartyProductName());
        esignOrderResaleDTO.setQuantity(BasicConstant.ONE);

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("orderId", orderId);
        List<FeeLogEntity> list = feeLogModel.findEntitys(param);

        if (list.size() == 0) {
            return ;
        }
        FeeLogEntity feeLog = list.get(0);
        esignOrderResaleDTO.setOrderCreateTime(list.get(0).getAddTime()*1000);
        esignOrderResaleDTO.setPayFee(feeEntity.getRealPrice());
        EsignOrderResaleVO esignOrderResaleVO = esignHelp.getEsignOrderResale(esignOrderResaleDTO);
        String esignOrderId = esignOrderResaleVO.getEsignOrderId();
        feeLog.setMemo(feeLog.getMemo() + "; e签宝订单id:" + esignOrderId);
        Long startTime = DateTimeUtil.getTodayInt();
        Long endTime = startTime + 365*86400;
        feeLog.setStartTime(startTime);
        feeLog.setEndTime(endTime);
        feeLogModel.update(feeLog);
    }

    public boolean saveNotifyEntity(Map<String, String> params) throws Exception {
        boolean flag = false;
        //getparam
        Date notifyTime = DateUtil.getDate(params.get("notify_time"), DateUtil.SDF);
        String notifyType = params.get("notify_type");
        String notifyId = params.get("notify_id");
        String signType = params.get("sign_type");
        String sign = params.get("sign");
        String subject = params.get("subject");
        String paymentType = params.get("payment_type");
        String outTradeNo = params.get("out_trade_no");
        String tradeNo = params.get("trade_no");
        String tradeStatus = params.get("trade_status");
        Date gmtCreate = DateUtil.getDate(params.get("gmt_create"), DateUtil.SDF);
        Date gmtPayment = DateUtil.getDate(params.get("gmt_payment"), DateUtil.SDF);
        //Date gmtClose=DateUtil.getDate( params.get("gmt_close")  ,DateUtil.SDF);//
        String sellerEmail = params.get("seller_email");
        String buyerEmail = params.get("buyer_email");
        String sellerId = params.get("seller_id");
        String buyerId = params.get("buyer_id");
        double price = StringUtil.toDouble(params.get("price"));
        double totalFee = StringUtil.toDouble(params.get("total_fee"));
        Integer quantity = StringUtil.toInt(params.get("quantity"));
        String body = params.get("body");
        //double discount =StringUtil.toDouble( params.get("discount") );//
        String isTotalFeeAdjust = params.get("is_total_fee_adjust");
        String useCoupon = params.get("use_coupon");
        //String refundStatus =  params.get("refund_status") ;//
        //Date gmtRefund=DateUtil.getDate( params.get("gmt_refund") ,DateUtil.SDF);//

        String isSuccess = params.get("is_success");
        //setEntity
        AlipayNotifyEntity alipayNotifyEntity = new AlipayNotifyEntity();
        alipayNotifyEntity.setIsSuccess(isSuccess);
        alipayNotifyEntity.setSignType(signType);
        alipayNotifyEntity.setSign(sign);
        alipayNotifyEntity.setNotifyId(notifyId);
        alipayNotifyEntity.setNotifyType(notifyType);
        alipayNotifyEntity.setNotifyTime(notifyTime);
        alipayNotifyEntity.setOutTradeNo(outTradeNo);
        alipayNotifyEntity.setTradeNo(tradeNo);
        alipayNotifyEntity.setTradeStatus(tradeStatus);
        alipayNotifyEntity.setSubject(subject);
        alipayNotifyEntity.setPaymentType(paymentType);
        //alipayNotifyEntity.setExterface(exterface);
        alipayNotifyEntity.setGmtCreate(gmtCreate);
        alipayNotifyEntity.setGmtPayment(gmtPayment);
//		alipayNotifyEntity.setGmtClose(gmtClose);
//		alipayNotifyEntity.setGmtRefund(gmtRefund);
//		alipayNotifyEntity.setRefundStatus(refundStatus);
        alipayNotifyEntity.setSellerEmail(sellerEmail);
        alipayNotifyEntity.setBuyerEmail(buyerEmail);
        alipayNotifyEntity.setSellerId(sellerId);
        alipayNotifyEntity.setBuyerId(buyerId);
        alipayNotifyEntity.setTotalFee(totalFee);
        alipayNotifyEntity.setPrice(price);
        alipayNotifyEntity.setBody(body);
//		alipayNotifyEntity.setExtraCommonParam(extraCommonParam);
//		alipayNotifyEntity.setAgentUserId(agentUserId);
//		alipayNotifyEntity.setOutChannelType(outChannelType);
//		alipayNotifyEntity.setOutChannelAmount(outChannelAmount);
//		alipayNotifyEntity.setOutChannelInst(outChannelInst);
        alipayNotifyEntity.setQuantity(quantity);
//		alipayNotifyEntity.setDiscount(discount);
        alipayNotifyEntity.setUseCoupon(useCoupon);
        alipayNotifyEntity.setIsTotalFeeAdjust(isTotalFeeAdjust);
        try {
            alipayNotifyModel.save(alipayNotifyEntity);
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error("saveNotifyEntity failed ,params=" + params, e);
            return false;
        }
        return flag;
    }
}
